/*
 * axiSrio.c - AXI SRIO设备驱动
 */

#include <vxWorks.h>
#include <vsbConfig.h>
#include <intLib.h>
#include <errnoLib.h>
#include <errno.h>
#include <sioLib.h>
#include <ioLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vxAtomicLib.h>
#include <semLib.h>
#include <sysLib.h>
#include <vmLib.h>
#include <hwif/vxBus.h>
#include <hwif/buslib/vxbFdtLib.h>
#include <private/vmLibP.h>
#include <pmapLib.h>
#include <taskLib.h>
#include "axiSrio.h"
#define INBOUND_ADDR 	0x3c000000
#define INBOUND_SIZE  	0x1000000
static STATUS axiSrioInited = ERROR;

/* VxBus方法 */
LOCAL STATUS axiSrioProbe(VXB_DEV_ID);
LOCAL STATUS axiSrioAttach(VXB_DEV_ID);

LOCAL VXB_DRV_METHOD axiSrioMethods[] = {
    { VXB_DEVMETHOD_CALL(vxbDevProbe), axiSrioProbe },
    { VXB_DEVMETHOD_CALL(vxbDevAttach), axiSrioAttach },
    VXB_DEVMETHOD_END
};

VXB_DRV axiSrioDrv = {
    { NULL },
    AXI_SRIO_NAME,          /* 驱动名称 */
    "AXI SRIO driver",      /* 描述 */
    VXB_BUSID_FDT,          /* 总线类型 */
    0,                      /* 标志 */
    0,                      /* 引用计数 */
    axiSrioMethods          /* 方法表 */
};

/* 设备树匹配表 */
LOCAL VXB_FDT_DEV_MATCH_ENTRY axiSrioMatch[] = {
    { "dd,axiSrio", (void *)NULL },
    {} /* 空终止列表 */
};

/* 设备打开函数 */
void axiSrioOpen(VXB_DEV_ID *ppDev, UINT32 unit) {
    if(axiSrioInited == ERROR)
        axiSrioInited = vxbDrvAdd(&axiSrioDrv);
    
    if(axiSrioInited == OK)
        *ppDev = vxbDevAcquireByName(AXI_SRIO_NAME, unit);
}

/* 设备关闭函数 */
int axiSrioClose(VXB_DEV_ID pDev) {
    return OK;
}


/* 寄存器读取函数 */
UINT32 axiSrioGet(VXB_DEV_ID pDev, UINT32 offset) {
    return CSR_READ_4(pDev, offset);
}

/* 寄存器写入函数 */
void axiSrioSet(VXB_DEV_ID pDev, UINT32 offset, UINT32 val) {
	CSR_WRITE_4(pDev, offset, val);
}
int cntsrioirq = 0 ;
LOCAL STATUS axiSrioHandler 
(
	VXB_DEV_ID pDev
)
{
	int i;
	cntsrioirq++; 
	UINT32 intStatus = axiSrioGet(pDev, FPGA_INT_STATUS_REG);
	axiSrioSet(pDev, FPGA_INT_STATUS_REG, 1); 

    SRIO_DRV_CTRL *pDrvCtrl = (SRIO_DRV_CTRL *)vxbDevSoftcGet(pDev);
    if (pDrvCtrl != NULL && pDrvCtrl->isr != NULL) {
        pDrvCtrl->isr(NULL);
    }
    return OK;
}


/* 探测函数 */
LOCAL STATUS axiSrioProbe(VXB_DEV_ID pDev) {
    return vxbFdtDevMatch(pDev, axiSrioMatch, NULL);
}

/* 附加函数 */
LOCAL STATUS axiSrioAttach(VXB_DEV_ID pDev) {
    VXB_RESOURCE *pRes;
    VXB_RESOURCE_ADR *pResAdr;
    SRIO_DRV_CTRL *pDrvCtrl;
    PHYS_ADDR physicalAddr;
    void *virtualAddr;
    size_t size = 0x8000000; // 1MB

    /* 分配驱动控制结构 */
    pDrvCtrl = vxbMemAlloc(sizeof(SRIO_DRV_CTRL));
    if(pDrvCtrl == NULL) {
        return ERROR;
    }
    bzero((char *)pDrvCtrl, sizeof(SRIO_DRV_CTRL));
    vxbDevSoftcSet(pDev, pDrvCtrl);
    pDrvCtrl->srioDev = pDev;

    /* 分配资源 */
    pRes = vxbResourceAlloc(pDev, VXB_RES_MEMORY, 0);
    if(pRes == NULL) {
        free(pDrvCtrl);
        return ERROR;
    }

    pResAdr = (VXB_RESOURCE_ADR *)pRes->pRes;
    if(pResAdr == NULL) {
        free(pDrvCtrl);
        return ERROR;
    }

    /* 获取虚拟地址空间 */
    pDrvCtrl->srioBar = (void *)pResAdr->virtual;
    if(vmTranslate(NULL, (VIRT_ADDR)pDrvCtrl->srioBar, &physicalAddr) == ERROR) {
        free(pDrvCtrl);
        return ERROR;
    }
    pDrvCtrl->srioPhyBar = physicalAddr;
    pDrvCtrl->srioHandle = pResAdr->pHandle;

    /* 分配1MB地址空间，物理地址八字节对齐 */
	UINT32 mmuAttr;
 	mmuAttr = MMU_ATTR_VALID | MMU_ATTR_SUP_RW | MMU_ATTR_CACHE_OFF;	
	virtualAddr=(UINT32*)pmapGlobalMap (INBOUND_ADDR,(size_t)INBOUND_SIZE,mmuAttr);
    if(virtualAddr == NULL) {
        free(pDrvCtrl);
        return ERROR;
    }
 


    pDrvCtrl->srioMem = virtualAddr;
    pDrvCtrl->srioMemPhyBar = INBOUND_ADDR;
 

    /* 创建信号量 */
    pDrvCtrl->srioSem = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);

    //对中断寄存器进行初始化
    axiSrioSet(pDev, FPGA_RESET_REG, FPGA_RESET_VALUE);
    axiSrioSet(pDev, FPGA_OUTPUT_LEVEL_REG,FPGA_OUT_LOW_IDLE);
    axiSrioSet(pDev, FPGA_INT_TYPE_REG, FPGA_INT_TYPE_LEVEL);
    axiSrioSet(pDev, FPGA_INT_POLARITY_REG, FPGA_INT_POL_RISING);
    axiSrioSet(pDev, FPGA_GLOBAL_ENABLE_REG, FPGA_GLOBAL_INT_ENABLE);
    axiSrioSet(pDev, FPGA_INT_ENABLE_REG, 1); 
    
    


    axiSrioSet(pDev, SRIO_TX_ADDR_REG, INBOUND_ADDR); 
    axiSrioSet(pDev, SRIO_DOORBELL_CFG_REG, 1); 
    axiSrioSet(pDev, SRIO_CTRL_REG, 7); 


  


   /* 获取中断资源 */
	pDrvCtrl->intRes = vxbResourceAlloc(pDev, VXB_RES_IRQ, 0);
	if(pDrvCtrl->intRes == NULL )
	{
	  logMsg("Failed to vxbResourceAlloc interrupt of device %s\n", (int)AXI_SRIO_NAME, 0, 0, 0, 0, 0);
	  return ERROR;
	}

	(void) vxbIntConnect (pDev, pDrvCtrl->intRes, (VOIDFUNCPTR) axiSrioHandler, pDev);
	(void) vxbIntEnable (pDev, pDrvCtrl->intRes);
	axiDmaOpen(&pDrvCtrl->admaDev, 0);

    return OK;
}



/* 中断注册函数 */
STATUS axiSrioIntConnect(VXB_DEV_ID pDev, VOIDFUNCPTR isr)
{

    SRIO_DRV_CTRL *pDrvCtrl;
    pDrvCtrl = vxbDevSoftcGet(pDev);
    if (pDrvCtrl == NULL) {
        return ERROR;
    }

    pDrvCtrl->isr = isr;

    return OK;
}


/* SRIO发送函数 */
STATUS axiSrioSend(VXB_DEV_ID pDev, const void *pData, UINT32 dataLen, UINT32 destId)
{    
    STATUS sendStatus = OK;
    int i;
    SRIO_DRV_CTRL *pDrvCtrl = (SRIO_DRV_CTRL *)vxbDevSoftcGet(pDev);
    if (pDrvCtrl == NULL)
        return ERROR;
   

    axiDmaTransfer(pDrvCtrl->admaDev, (UINT32)pData, dataLen);

    return OK;
}

/* SRIO接收地址获取函数 */
void *axiSrioGetRxAddr(VXB_DEV_ID pDev)
{
    SRIO_DRV_CTRL *pDrvCtrl = (SRIO_DRV_CTRL *)vxbDevSoftcGet(pDev);
    if (pDrvCtrl == NULL)
        return NULL;

    // 这里需要根据实际硬件和协议实现具体的获取逻辑
    // 示例代码仅占位，实际使用时需替换
    return pDrvCtrl->srioMem;
}


